package ajakuulauku;

/**
 * A two dimensional Vector
 * 
 * @author Janno Tomingas
 */
public class Vector2 {

	/**
	 * The Vector2's coordinates
	 */
	public double X;
	public double Y;
	
	
	/**
	 * Generates a new Vector2
	 */
	public Vector2() {
		
	}
	
	/**
	 * Generates a new Vector2
	 * @param a, GameObject
	 */
	public Vector2(GameObject a) {
		X = a.getX();
		Y = a.getY();
	}
	
	/**
    * Generates a new Vector2
    * @param x coordinate, double
    * @param y coordinate, double
    */
	public Vector2(double x, double y) {
		X = x;
		Y = y;
	}
	
	/**
	* Adds the parameter to the Vector2
	* @param a, Vector2
	* @returns result, Vector2
	*/	
	public Vector2 add(Vector2 a) {
		Vector2 tmp = new Vector2();
		
		tmp.X = this.X + a.X;
		tmp.Y = this.Y + a.Y;
		
		return tmp;
	}
	
	/**
	* Adds to the Vector2's length by parameter a
	* @param a, double
	* @returns result, Vector2
	*/	
	public Vector2 add(double a) {
		Vector2 tmp = new Vector2(this.X, this.Y);
		
		double length = tmp.length();
		tmp = tmp.normalize();
		
		double newLength = length + a;
		if (newLength < 0) {
			newLength = 0;
		}
		tmp.X = tmp.X * (newLength);
		tmp.Y = tmp.Y * (newLength);
		
		return tmp;
	}
	
	/**
	* Subtracts the parameter from the Vector2
	* @param a, Vector2
	* @returns result, Vector2
	*/
	public Vector2 subtract(Vector2 a) {
		Vector2 tmp = new Vector2();
		
		tmp.X = this.X - a.X;
		tmp.Y = this.Y - a.Y;
		
		return tmp;
	}
	
	/**
	* Reduces the Vector2's length by parameter a
	* @param a, double
	* @returns result, Vector2
	*/	
	public Vector2 subtract(double a) {
		Vector2 tmp = new Vector2(this.X, this.Y);
		
		double length = tmp.length();
		tmp = tmp.normalize();
		
		double newLength = length - a;
		
		if (newLength < 0) {
			newLength = 0;
		}
		tmp.X = tmp.X * (newLength);
		tmp.Y = tmp.Y * (newLength);
		
		return tmp;
	}
	
	/**
	* Multiplies the Vector2 by parameter a
	* @param a, double
	* @returns result, Vector2
	*/
	public Vector2 multiplyBy(double a) {
		Vector2 tmp = new Vector2();
		tmp.X = this.X * a;
		tmp.Y = this.Y * a;
		
		return tmp;
	}
	
	/**
	* Divides the Vector2 by parameter a
	* @param a, double
	* @returns result, Vector2
	*/
	public Vector2 divideBy(double a) {
		Vector2 tmp = new Vector2();
		tmp.X = this.X / a;
		tmp.Y = this.Y / a;
		
		return tmp;
	}
	
	/**
    * Normalizes the Vector2
    * @returns result, Vector2
    */
	public Vector2 normalize() {
		double length = this.length();
		
		if (length > 0) {
		Vector2 tmp = this;
		tmp = tmp.divideBy(length);
		return tmp;
		}
		
		else return new Vector2();
	}
	
	/**
	 * Compares the Vector2 to a
	 * @param a, Vector2
	 * @return 1 if a is smaller, 0 if they are equal, -1 if a is greater
 	 */
	public int compareTo(Vector2 a) {
		if (this.length() > a.length()){
			return 1;
		}
		
		else if (this.length() == a.length()){
			return 0;
		}
		
		else return -1;
	}
	
	/**
	 * Returns the Vector2 as a double[] array
	 * @return result, double[]
	 */
	public double[] toArray() {
		double[] tmp = new double[] {this.X, this.Y};
		return tmp;
	}
	
	/**
	 * Floors the Vector2
	 */
	public void toInt() {
		this.X = (int)this.X;
		this.Y = (int)this.Y;
		return;
	}
	
	/**
    * Clones the Vector2
    * @param a, Vector2
    * @returns clone, Vector2
    */
	public Vector2 clone() {
		Vector2 tmp = new Vector2(this.X, this.Y);
		
		return tmp;
	}
	
	/**
    * Gets the Vector2's length
    * @returns length, double
    */
	public double length() {
		double length;
		
		double sqrt = Math.pow(this.X, 2) + Math.pow(this.Y, 2);
		length = Math.sqrt(sqrt);
		
		return length;
	}
	
	/**
	 * Returns the Vector2's coordinates in a readable String format
	 */
	public String toString(){
		return (this.X + ":" + this.Y);
	}
	
	public boolean equals(Vector2 arg) {
		if (this.X == arg.X && this.Y == arg.Y) {
			return true;
		}
		else return false;
	}
	
	/**
	 * Clears the vector
	 */
	public void clear() {
		this.X = 0;
		this.Y = 0;
	}

	public double dot(Vector2 B) {
		double dotProduct = (this.X * B.X + this.Y * B.Y);

		return dotProduct;
	}
	
	public static double angle(Vector2 A, Vector2 B) {
		double angle;
		angle = Math.acos((A.X * A.Y + B.X * B.Y) / (A.length() * B.length()));
		return angle;
	}
	
	public Vector2 setLength(double leng) {
		this.normalize();
		this.multiplyBy(leng);
		return this;
	}
}
